package io.renren.modules.workmanagement.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.renren.common.exception.RRException;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.Query;
import io.renren.modules.workmanagement.constans.UserConstans;
import io.renren.modules.workmanagement.dao.QuestionDao;
import io.renren.modules.workmanagement.entity.*;
import io.renren.modules.workmanagement.enums.AnswerEnum;
import io.renren.modules.workmanagement.enums.QuTypeEnums;
import io.renren.modules.workmanagement.service.*;
import io.renren.modules.workmanagement.utils.PojoUtils;
import io.renren.modules.workmanagement.vo.AnswerDetailVO;
import io.renren.modules.workmanagement.vo.QuestionAnswerVO;
import io.renren.modules.workmanagement.vo.qu.AnswerVO;
import io.renren.modules.workmanagement.vo.qu.QuestionInfoVO;
import io.renren.modules.workmanagement.vo.qu.QuestionVO;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;


@Service("questionService")
public class QuestionServiceImpl extends ServiceImpl<QuestionDao, QuestionEntity> implements QuestionService {
    @Autowired
    private QuestionAnswerService questionAnswerService;
    @Autowired
    private QuestionBankService questionBankService;
    @Autowired
    private QuRepoService quRepoService;
    @Autowired
    private WorkAnswerService workAnswerService;
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        LambdaQueryWrapper<QuestionEntity> wrapper = new LambdaQueryWrapper<>();
        Long userId = (Long) params.get(UserConstans.USER_ID_KEY);
        String bankId = (String) params.get("bankId");
        String key = (String) params.get("key");
        if(StringUtils.isNotBlank(key)){
            wrapper.like(QuestionEntity::getContent, key);
        }
        if(StringUtils.isNotBlank(bankId)){
            List<QuRepoEntity> quRepoEntities = quRepoService.listByQuBankId(Long.parseLong(bankId));
            List<Long> quIds = PojoUtils.streamMapList(quRepoEntities, QuRepoEntity::getQuId);
            if(CollectionUtil.isEmpty(quIds)){
                throw new RRException("该题库下没有题目");
            }
            wrapper.in(QuestionEntity::getId, quIds);
        }
        IPage<QuestionEntity> page = this.page(
                new Query<QuestionEntity>().getPage(params),
                wrapper.eq(QuestionEntity::getCreateUser, userId)
        );

        return new PageUtils(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveQuestion(QuestionVO question, Long userId) {
        //保存题目
        QuestionEntity questionEntity = new QuestionEntity();
        questionEntity.setCreateUser(userId);
        questionEntity.setQuType(question.getQuType());
        questionEntity.setLevel(question.getLevel());
        questionEntity.setContent(question.getContent());
        questionEntity.setAnalysis(question.getAnalysis());
        this.save(questionEntity);

        List<Long> questionBankIds = question.getQuestionBankIds();
        //更新题库数量
        List<QuestionBankEntity> questionBankEntities = questionBankService.listByIds(questionBankIds);
        questionBankEntities.forEach(questionBankEntity -> addLevelCount(questionBankEntity, question.getQuType()));
        questionBankService.updateBatchById(questionBankEntities);

        Long questionId = questionEntity.getId();
        List<AnswerVO> answers = question.getAnswers();
        if(CollectionUtil.isEmpty(answers)){
            throw new RRException("请至少添加一个答案");
        }
        //保存题目答案
        List<QuestionAnswerEntity> answerEntities = answers.stream().map(answer -> {
            QuestionAnswerEntity questionAnswerEntity = new QuestionAnswerEntity();
            questionAnswerEntity.setQuId(questionId);
            questionAnswerEntity.setIsRight(answer.getIsRight());
            questionAnswerEntity.setContent(answer.getContent());
            questionAnswerEntity.setAnalysis(answer.getAnalysis());
            return questionAnswerEntity;
        }).collect(Collectors.toList());
        questionAnswerService.saveBatch(answerEntities);

        //保存题目与题库关联
        List<QuRepoEntity> quRepoEntities = questionBankIds.stream().map(questionBankId -> {
            QuRepoEntity quRepoEntity = new QuRepoEntity();
            quRepoEntity.setQuId(questionId);
            quRepoEntity.setRepoId(questionBankId);
            quRepoEntity.setQuType(question.getQuType());
            quRepoEntity.setSort(0);
            return quRepoEntity;
        }).collect(Collectors.toList());
        quRepoService.saveBatch(quRepoEntities);
    }

    @Override
    public QuestionInfoVO getQuestionInfoVO(Long id) {
        QuestionInfoVO questionInfoVO = new QuestionInfoVO();

        QuestionEntity questionEntity = this.getById(id);
        BeanUtils.copyProperties(questionEntity, questionInfoVO);

        List<QuRepoEntity> quRepoEntities = quRepoService.ListByQuestionId(id);
        List<Long> bankIds = quRepoEntities.stream().map(QuRepoEntity::getRepoId).collect(Collectors.toList());
        questionInfoVO.setQuestionBankId(bankIds);

        List<QuestionAnswerEntity> answerEntities = questionAnswerService.ListByQuestionId(id);
        int index = 0;
        List<AnswerVO> answerVOS = new ArrayList<>(answerEntities.size());
        List<Integer> answerIndexList = new ArrayList<>();
        for (QuestionAnswerEntity answerEntity : answerEntities) {
            AnswerVO answerVO = new AnswerVO();
            answerVO.setIsRight(answerEntity.getIsRight());
            answerVO.setContent(answerEntity.getContent());
            answerVO.setAnalysis(answerEntity.getAnalysis());
            answerVOS.add(answerVO);
            if (answerEntity.getIsRight().equals(AnswerEnum.TRUE.getCode())) {
                answerIndexList.add(index);
            }
            index++;
        }
        questionInfoVO.setAnswerList(answerVOS);
        questionInfoVO.setAnswerIndex(answerIndexList);
        return questionInfoVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateQuestion(QuestionVO questionVO, Long userId) {
        List<Long> questionBankIds = questionVO.getQuestionBankIds();
        if (CollectionUtil.isEmpty(questionBankIds)) {
            throw new RRException("归属题库不能为空");
        }

        QuestionEntity question = this.getById(questionVO.getId());
        Integer oldQuType = question.getQuType();
        question.setCreateUser(userId);
        question.setQuType(questionVO.getQuType());
        question.setLevel(questionVO.getLevel());
        question.setContent(questionVO.getContent());
        question.setAnalysis(questionVO.getAnalysis());
        this.updateById(question);

        List<QuestionBankEntity> questionBankEntities = questionBankService.listByIds(questionBankIds);
        if (!oldQuType.equals(questionVO.getQuType())) {
            //题库对应原始类型数量-1
            questionBankEntities.forEach(item -> subOneLevelCount(item, oldQuType));
            //对应新类型数量+1
            questionBankEntities.forEach(item -> addLevelCount(item, questionVO.getQuType()));
            questionBankService.updateBatchById(questionBankEntities);
        }
        //删除题目答案
        questionAnswerService.removeByQuId(question.getId());
        List<AnswerVO> answers = questionVO.getAnswers();
        //保存题目答案
        List<QuestionAnswerEntity> answerEntities = answers.stream().map(answer -> {
            QuestionAnswerEntity questionAnswerEntity = new QuestionAnswerEntity();
            questionAnswerEntity.setQuId(questionVO.getId());
            questionAnswerEntity.setIsRight(answer.getIsRight());
            questionAnswerEntity.setContent(answer.getContent());
            questionAnswerEntity.setAnalysis(answer.getAnalysis());
            return questionAnswerEntity;
        }).collect(Collectors.toList());
        questionAnswerService.saveBatch(answerEntities);


        //删除题目与所有题库关联
        quRepoService.removeByQuId(question.getId());
        List<QuRepoEntity> quRepoEntities = questionBankIds.stream().map(questionBankId -> {
            QuRepoEntity quRepoEntity = new QuRepoEntity();
            quRepoEntity.setQuId(questionVO.getId());
            quRepoEntity.setRepoId(questionBankId);
            quRepoEntity.setQuType(questionVO.getQuType());
            quRepoEntity.setSort(0);
            return quRepoEntity;
        }).collect(Collectors.toList());
        quRepoService.saveBatch(quRepoEntities);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeQuestion(List<Long> quIds) {
        List<QuestionEntity> questionEntities = this.listByIds(quIds);
        //删除题目
        this.removeByIds(quIds);
        //查询题目关联的题库
        List<Long> questionBankIds = PojoUtils.streamMapList(quRepoService.listByQuIds(quIds), QuRepoEntity::getRepoId);
        List<QuestionBankEntity> questionBankEntities = questionBankService.listByIds(questionBankIds);
        Map<Integer, Long> quTypeCountMap = questionEntities.stream().collect(Collectors.groupingBy(QuestionEntity::getQuType, Collectors.counting()));
        //删除题库对应类型数量
        quTypeCountMap.forEach((k,v)-> questionBankEntities.forEach(item-> subLevelCount(item,k,v.intValue())));
        questionBankService.updateBatchById(questionBankEntities);
        //删除题目与题库关联
        quRepoService.removeByQuIds(quIds);
        //删除题目答案
        questionAnswerService.removeByQuIds(quIds);

    }

    @Override
    public QuestionAnswerVO getQuestionAnswers(Long workId, Long quId, Long userId) {
        List<WorkAnswerEntity> workAnswerList = workAnswerService.getByWorkIdAndUserIdAndQuId(workId,quId,userId);
        QuestionEntity question = this.getById(quId);
        QuestionAnswerVO questionAnswerVO = new QuestionAnswerVO();
        questionAnswerVO.setQuId(quId);
        questionAnswerVO.setQuType(question.getQuType());
        List<QuestionAnswerEntity> questionAnswerEntityList = questionAnswerService.ListByQuestionId(quId);
        List<AnswerDetailVO> collect = questionAnswerEntityList.stream().map(item -> {
            Boolean checked = Optional.ofNullable(workAnswerList)
                    .filter(CollectionUtil::isNotEmpty)
                    .map(list -> PojoUtils.streamMapList(list,WorkAnswerEntity::getAnswer))
                    .map(answerIds -> answerIds.contains(item.getId()))
                    .orElse(false);
            AnswerDetailVO answerDetailVO = new AnswerDetailVO();
            answerDetailVO.setId(item.getId());
            answerDetailVO.setChecked(checked);
            answerDetailVO.setContent(item.getContent());
            return answerDetailVO;
        }).collect(Collectors.toList());
        questionAnswerVO.setContent(question.getContent());
        questionAnswerVO.setAnswerList(collect);
        questionAnswerVO.setSort(0);
        return questionAnswerVO;
    }

    private void addLevelCount(QuestionBankEntity questionBankEntity, int quType) {
        if (quType == QuTypeEnums.RADIO.getQuType()) {
            questionBankEntity.setRadioCount(questionBankEntity.getRadioCount() + 1);
            return;
        }
        if (quType == QuTypeEnums.CHECKBOX.getQuType()) {
            questionBankEntity.setMultiCount(questionBankEntity.getMultiCount() + 1);
            return;
        }
        if (quType == QuTypeEnums.JUDGE.getQuType()) {
            questionBankEntity.setJudgeCount(questionBankEntity.getJudgeCount() + 1);
            return;
        }
    }


    private void subOneLevelCount(QuestionBankEntity questionBankEntity, int level) {
        subLevelCount(questionBankEntity,level,1);
    }

    private void subLevelCount(QuestionBankEntity questionBankEntity, int level, Integer num) {
        if (level == QuTypeEnums.RADIO.getQuType()) {
            questionBankEntity.setRadioCount(questionBankEntity.getRadioCount() - num);
            return;
        }
        if (level == QuTypeEnums.CHECKBOX.getQuType()) {
            questionBankEntity.setMultiCount(questionBankEntity.getMultiCount() - num);
            return;
        }
        if (level == QuTypeEnums.JUDGE.getQuType()) {
            questionBankEntity.setJudgeCount(questionBankEntity.getJudgeCount() - num);
            return;
        }
    }
}
